<?PHP

/**
 * 数据操作类
 *
 * @author     Robot
 * @version    1.0
 * @package    Base Framework
 * @access     public
 * @copyright  商业软件,受著作权保护
 * @link       http://***
 */
abstract class InitDMO
{
	/**
	 * 数据库操作对象
	 *
	 * @var    object
	 * @access protected
	 */
	protected $_db;
	
	/**
	 * 数据表
	 *
	 * @var    object
	 * @access protected
	 */
	protected $_table;
	
	/**
	 * 数据表主键
	 *
	 * @var    object
	 * @access protected
	 */
	protected $_key;
	
	/**
	 * 字段属性
	 *
	 * @var    array
	 * @access private
	 */
	public $field;
	
	/**
	 * 构造函数
	 *
	 * @access public
	 * @param  void
	 * @return void
	 */
	function __construct()
	{
		$this->mysql = new PDOMySQL($this->_db, $this->_table);
	}
	
	/**
	 * HashTable
	 *
	 * @access public
	 * @param  void
	 * @return void
	 */
	public function getHashTable($hashnum = 0)
	{
		$iHashid = $hashnum % $this->_hashnum;
		return $this->_table . '_' . $iHashid;
	}
	
	/**
	 * 获取总条数
	 *
	 * @access public
	 * @param  void
	 * @return void
	 */
	public function prepare($sql)
	{
		return $this->mysql->prepare($sql);
	}
	
	/**
	 * 执行sql语句
	 *
	 * @param none
	 * @return int $insert_id
	 */
	public function exec($sql)
	{
		return $this->mysql->exec($sql);
	}

	/**
	 * 获取总条数
	 *
	 * @access public
	 * @param  void
	 * @return void
	 */
	public function getTotal()
	{
		return intval($this->mysql->total);
	}
	
	/**
	 * 获得insertID
	 *
	 * @param none
	 * @return int $insert_id
	 */
	public function getInsertId()
	{
		return $this->mysql->getLastId();
	}
	
	/**
	 * 获取count(*)
	 *
	 * @access public
	 * @param  Array
	 * @return int
	 */
	public function getCount($aKey = '')
	{
		$_table = $this->_hashfield ? $this->getHashTable($aKey[$this->_hashfield]) : $this->_table;

		$sql = "SELECT count(*) FROM {$_table} " . $this->setAKey($aKey);

		return $this->mysql->getOne($sql);
	}
	
	/**
	 * 判断是否存在
	 *
	 * @access public
	 * @param  object
	 * @param  string
	 * @param  string
	 * @return boolean
	 */
	public function exist($oDTO, $sKey = '')
	{
		if($this->_hashfield)
		{
			$f = $this->_hashfield;
			$_table = $this->getHashTable($oDTO->$f);
		}
		else
		{
			$_table = $this->_table;
		}

		$sql = "SELECT count(*) FROM {$_table} " . $this->setSKey($oDTO, $sKey);
		
		return (boolean)$this->mysql->getOne($sql);
	}
	
	/**
	 * 插入一条数据
	 *
	 * @access public
	 * @param  object
	 * @return boolean
	 */
	public function add($oDTO)
	{
		if($this->_hashfield)
		{
			foreach(explode(",", $this->field) as $field)
			{
				$method = "get" . ucfirst($field);
				$methodValue = $oDTO->$method();
				self::injectCheck($methodValue);
				$aField[] = "'" . $methodValue . "'";
				if($this->_hashfield == $field)
				{
					$_table = $this->getHashTable($oDTO->$method());
				}
			}
		}
		else
		{
			foreach(explode(",", $this->field) as $field)
			{
				$method = "get" . ucfirst($field);
				$methodValue = $oDTO->$method();
				self::injectCheck($methodValue);
				$aField[] = "'" . $methodValue . "'";
			}
			$_table = $this->_table;
		}

		$sql = "INSERT INTO {$_table} ({$this->getField()}) VALUES (" . join(",", $aField) . ")";
		if($this->mysql->exec($sql) === false)
		{
			return false;
		}
		return true;
	}
	
	/**
	 * 删除一条记录
	 *
	 * @access public
	 * @param  Object
	 * @param  String
	 * @return boolean
	 */
	public function remove($oDTO, $sKey = '')
	{
		if($this->_hashfield)
		{
			$f = $this->_hashfield;
			$_table = $this->getHashTable($oDTO->$f);
		}
		else
		{
			$_table = $this->_table;
		}

		$sql = "DELETE FROM {$_table} " . $this->setSKey($oDTO, $sKey);
		
		if($this->mysql->exec($sql) === false)
		{
			return false;
		}
		
		return true;
	}
	
	/**
	 * 获取一条记录
	 *
	 * @access public
	 * @param  object
	 * @param  String
	 * @return boolean
	 */
	public function get($oDTO, $sKey = '')
	{
		if($this->_hashfield)
		{
			$f = $this->_hashfield;
			$_table = $this->getHashTable($oDTO->$f);
		}
		else
		{
			$_table = $this->_table;
		}

		$sql = "SELECT {$this->getField()} FROM {$_table} " . $this->setSKey($oDTO, $sKey) . " LIMIT 1";
		
		$oRes = $this->mysql->getRow($sql, PDO::FETCH_OBJ);
		
		if($oRes === false)
		{
			return false;
		}
		
		$this->copyDto($oDTO, $oRes);
		return true;
	}
	
	/**
	 * 获取一条记录
	 *
	 * @access public
	 * @param  object
	 * @param  String
	 * @return boolean
	 */
	public function getRow($aKey, $aOrder = '')
	{
		$_table = $this->_hashfield ? $this->getHashTable($aKey[$this->_hashfield]) : $this->_table;
		$sql = "SELECT {$this->getField()} FROM {$_table} " . $this->setAKey($aKey) . $this->setAOrder($aOrder) . " LIMIT 1";
		
		return $this->mysql->getRow($sql, PDO::FETCH_ASSOC);
	}
	
	/**
	 * 修改一条记录
	 *
	 * @access public
	 * @param  Object
	 * @param  string $sKey
	 * @return boolean
	 */
	public function modify($oDTO, $sKey = '')
	{
		if($this->_hashfield)
		{
			$f = $this->_hashfield;
			$_table = $this->getHashTable($oDTO->$f);
		}
		else
		{
			$_table = $this->_table;
		}

		$method = "get" . ucfirst($this->_key);
		foreach(explode(",", $this->field) as $field)
		{
			if($field != $this->_key)
			{
				$methodTmp = "get" . ucfirst($field);
				$methodValue = $oDTO->$methodTmp();
				self::injectCheck($methodValue);

				$aField[] = " `$field`= '" . $methodValue . "' ";
			}
		}
		
		$sql = "UPDATE {$_table} SET " . join(",", $aField) . $this->setSKey($oDTO, $sKey);
		if($this->mysql->exec($sql) === false)
		{
			return false;
		}
		
		return true;
	}
	
	/**
	 * 获取多条记录,分页
	 *
	 * @access public
	 * @param  int $iStart 开始行数,
	 * @param  int $iNumber 记录数,
	 * @param  string $sOrder 主键排序方式
	 * @return boolean
	 */
	public function getPage($iStart = 0, $iNumber = 10, $aKey, $aOrder = '')
	{
		$_table = $this->_hashfield ? $this->getHashTable($aKey[$this->_hashfield]) : $this->_table;

		$sql = "SELECT SQL_CALC_FOUND_ROWS {$this->getField()} FROM {$_table} " . $this->setAKey($aKey) . $this->setAOrder($aOrder) . " LIMIT $iStart,$iNumber ";

		return $this->mysql->getAlls($sql, PDO::FETCH_ASSOC);
	}
	
	/**
	 * 获取多条记录,不分页
	 *
	 * @access public
	 * @param  int $iStart 开始行数,
	 * @param  int $iNumber 记录数,
	 * @param  string $sOrder 主键排序方式
	 * @return boolean
	 */
	public function getAll($aKey, $aOrder = '', $sGroup='')
	{
		$_table = $this->_hashfield ? $this->getHashTable($aKey[$this->_hashfield]) : $this->_table;

		$sql = "SELECT {$this->getField()} FROM {$_table} " . $this->setAKey($aKey) . $this->setSGroup($sGroup) . $this->setAOrder($aOrder);

		return $this->mysql->getAlls($sql, PDO::FETCH_ASSOC);
	}
	
	/**
	 * 获取多条记录,不分页
	 *
	 * @access public
	 * @param  int $iStart 开始行数,
	 * @param  int $iNumber 记录数,
	 * @param  string $sOrder 主键排序方式
	 * @return boolean
	 */
	public function getAllWithSql($sql, $aOrder = '', $sGroup='')
	{
		$sql = $sql . $this->setSGroup($sGroup) . $this->setAOrder($aOrder);

		return $this->mysql->getAlls($sql, PDO::FETCH_ASSOC);
	}

	/**
	 * 获取前TOP条记录
	 *
	 * @access public
	 * @param  int $iNumber 记录数,
	 * @param  string $sOrder 主键排序方式
	 * @return boolean
	 */
	public function getTop($aKey, $iNumber = 10, $aOrder = '')
	{
		$_table = $this->_hashfield ? $this->getHashTable($aKey[$this->_hashfield]) : $this->_table;

		$sql = "SELECT {$this->getField()} FROM {$_table} " . $this->setAKey($aKey) . $this->setAOrder($aOrder) . " LIMIT $iNumber ";

		return $this->mysql->getAlls($sql, PDO::FETCH_ASSOC);
	}

	/**
	 *
	 *
	 * @access public
	 * @param  void
	 * @return void
	 */
	function setTable($table)
	{
		$this->_table = $table;
	}
	
	/**
	 * 设置字段
	 *
	 * @access public
	 * @param  void
	 * @return void
	 */
	function setField($field)
	{
		$this->field = $field;
	}
	
	/**
	 * 获得字段
	 *
	 * @access public
	 * @param  void
	 * @return void
	 */
	function getField()
	{
		return $this->field;
	}
	
	/**
	 * 数据对象复制，将对象2的属性复制给对象1
	 *
	 * @access protected
	 * @param  object $obj1
	 * @param  object $obj2
	 * @return void
	 */
	public function copyDto($o1, $o2)
	{
		$aVars = get_object_vars($o2);
		if($aVars)
		{
			foreach($aVars as $key => $value)
			{
				if($value)
				{
					$o1->$key = $o2->$key;
				}
			}
		}
	}
	
	/**
	 * 设置数组类型条件
	 *
	 * @access public
	 * @param  void
	 * @return void
	 */
	function setAKey($aKey = '')
	{
		if($aKey && is_array($aKey))
		{
			foreach($aKey as $k => $v)
			{
				is_string($v) && self::injectCheck($v);
				is_array($v) && self::injectCheck($v[0]) && self::injectCheck($v[1]);

				$ft1 = substr($k, 0, 1);

				//多字段
				if(strpos($k, "|"))
				{
					$_fs = array();
					$fArr = explode("|", substr($k, 1));

					foreach($fArr as $k)
					{
						if($ft1 == '%')
						{
							$_fs[] = " {$k} like '%" . $v . "%' ";
						}
						else if($ft1 == '=')
						{

							$_s[] = " `{$k}` = '" . $v . "' ";
						}
					}

					$_s[] = "(".join(" OR ", $_fs).")";
				}
				else
				{

					//!=的情况
					if($ft1 == '!')
					{
						$k = str_replace("!", "", $k);
						$_s[] = " `{$k}` != '" . $v . "' ";
					}
					//like的情况
					elseif($ft1 == '%')
					{
						$k = str_replace("%", "", $k);
						$_s[] = " {$k} like '%" . $v . "%' ";
					}
					//in的情况
					else if($ft1 == "+")
					{
						if(!$v)
						{
							return " WHERE 0";
						}
						$k = str_replace("+", "", $k);
						$_s[] = " `{$k}` in (" . $v . ") ";
					}
					//not in的情况
					else if($ft1 == "^")
					{
						if(!$v)
						{
							return " WHERE 0";
						}
						$k = str_replace("^", "", $k);
						$_s[] = " `{$k}` not in (" . $v . ") ";
					}
					//位运算的情况
					else if($ft1 == "&")
					{
						$k = str_replace("&", "", $k);
						$_s[] = " substring(`{$k}`, " . $v . ", 1)=1 ";
					}
					//大于的情况
					else if($ft1 == ">")
					{
						$k = str_replace(">", "", $k);
						$_s[] = " `{$k}` > '" . $v . "' ";
					}
					//小于的情况
					else if($ft1 == "<")
					{
						$k = str_replace("<", "", $k);
						$_s[] = " `{$k}` < '" . $v . "' ";
					}
					//大于等于的情况
					else if($ft1 == "[")
					{
						$k = str_replace("[", "", $k);
						$_s[] = " `{$k}` >= '" . $v . "' ";
					}
					//小于等于的情况
					else if($ft1 == "]")
					{
						$k = str_replace("]", "", $k);
						$_s[] = " `{$k}` <= '" . $v . "' ";
					}
					//双区间
					else if ($ft1 == "-")
					{
						$ft2 = substr($k, 1, 1);
						$ft3 = substr($k, -1, 1);
						$field = substr($k,2,-1);

						$s = "";
						if($ft2 == "[")
						{
							$s .= " `{$field}` >= '$v[0]'";
						}
						else if($ft2 == "(")
						{
							$s .= " `{$field}` > '$v[0]'";
						}
						$s .= " and";
						if($ft3 == "]")
						{
							$s .= " `{$field}` <= '$v[1]'";
						}
						else if($ft3 == ")")
						{
							$s .= " `{$field}` < '$v[1]'";
						}

						$_s [] = $s;
					}
					//等于的情况
					else
					{

						$_s[] = " `{$k}` = '" . $v . "' ";
					}
				}
			}

			return " WHERE " . join(" AND ", $_s);
		}
	}
	
	/**
	 * 设置字符类型条件
	 *
	 * @access public
	 * @param  void
	 * @return void
	 */
	function setSKey($oDTO, $sKey = '')
	{
		if(!$sKey && !$this->_key)
		{
			throw new MyException(get_class($oDTO)." table missing primary key.");
		}

		$sKey = $sKey ? $sKey : $this->_key;
		$aKey = explode(",", $sKey);
		
		foreach((array)$aKey as $v)
		{
			$ft1 = substr($v, 0, 1);
			$lt1 = substr($v, -1, 1);
			$lt2 = substr($v, -2, 2);
			
			// !=的情况
			if($ft1 == '!')
			{
				$k = str_replace("!", "", $v);
				$method = "get" . ucfirst($k);
				$methodValue = $oDTO->$method();
				self::injectCheck($methodValue);

				$_s[] = " `{$k}` != '" . $methodValue . "' ";
			}
			else // =的情况
			{
				$method = "get" . ucfirst($v);
				$methodValue = $oDTO->$method();
				self::injectCheck($methodValue);
				$_s[] = " `{$v}` = '" . $methodValue . "' ";
			}
		}
		return " WHERE " . join("AND", $_s);
	}
	
	/**
	 * 设置Order条件
	 *
	 * @access public
	 * @param  void
	 * @return void
	 */
	function setAOrder($aKey = '')
	{
		if(!$aKey)
		{
			return "";
		}
		if(is_string($aKey)){
			return $aKey;
		}
		foreach($aKey as $k => $v)
		{
			$_s[] = $k . ' ' . $v;
		}
		return ' ORDER BY ' . join(",", $_s);
	}
	
	/**
	 * 设置Group条件
	 *
	 * @access public
	 * @param  void
	 * @return void
	 */
	function setSGroup($sKey = '')
	{
		if(!$aKey)
		{
			return "";
		}
		
		return ' GROUP BY ' . $sKey;
	}
	
	/**
	 * 设置Group条件
	 *
	 * @access public
	 * @param  void
	 * @return void
	 */
	function injectCheck($str)
	{
		$match = preg_match("/select|insert|update|delete|load_file|outfile/i", $str);

		if($match)
		{
			error_log("[SQL Err,Illegal access]".$str, 0);
			throw new MyException("sql Err,Illegal access.");
		}

		return $match;
	}
}

//end class InitDMO
?>